<?php
declare(strict_types=1);

namespace App\Service;

use App\Model\Dao\ChannelCollectionConnDao;
use App\Model\Dao\ChannelInfoDao;
use App\Utils\CustomUtils;
use App\Utils\StringUtils;
use Hyperf\Database\Query\Builder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\ChannelCollectionDao;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;
use Hyperf\Utils\Arr;

class ChannelCollectionService {

    /**
     * @Inject()
     * @var ChannelCollectionDao
     */
    private $ChannelCollectionDao;

    /**
     * @Inject()
     * @var ChannelCollectionConnDao
     */
    private $ChannelCollectionConnDao;

    /**
     * @Inject()
     * @var ChannelInfoDao
     */
    private $ChannelInfoDao;

    /**
     * @Inject()
     * @var RiskSyncService
     */
    private $RiskSyncService;

    /**
     * 列表
     *
     * @param array $param
     *
     * @return array
     */
    public function list (array $param) {

        $limit = $param['limit'];
        $page  = $param['page'];

        $total = $this->ChannelCollectionDao->getCount($param);
        $list  = $this->ChannelCollectionDao->getList($param, $page, $limit);

        $list = CustomUtils::formatCreateTime($list);

        $data = [
            'total' => $total,
            'list'  => $list,
        ];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $data);
    }

    /**
     * 详情
     *
     * @param $param
     *
     * @return array
     */
    public function get ($param) {

        $id = $param['id'];

        $result = $this->ChannelCollectionDao->get($id);

        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $conn = $this->ChannelCollectionDao->getChannelListByCollectionId($id);

        $result         = CustomUtils::formatCreateTime($result);
        $result['conn'] = CustomUtils::formatCreateTime($conn);

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $result);
    }

    /**
     * 从参数过滤得到添加/更新数组
     *
     * @param $param
     *
     * @return array
     */
    protected function _filterUpdate ($param) {

        $update = Arr::only($param, [
            'status',
            'collectionName',
        ]);

        return $update;
    }

    /**
     * 添加
     *
     * @param $param
     *
     * @return array
     * @throws \Throwable
     */
    public function add ($param) {

        $update            = $this->_filterUpdate($param);
        $update            = array_merge($update, Arr::only($param, ['createBy', 'updateBy']));
        $update['payType'] = $param['payType'];

        $id = StringUtils::uuidV4();

        $update['id'] = $id;

        Db::beginTransaction();

        try {
            $this->ChannelCollectionDao->insert($update);

            $this->_setConn($id, $param);

        } catch (\Exception $e) {

            Db::rollBack();
            throw $e;
        }

        Db::commit();

        $data = ['id' => $id];

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), $data);
    }

    /**
     * 编辑
     *
     * @param $param
     *
     * @return array
     */
    public function edit ($param) {

        $id = Arr::pull($param, 'id');

        $info = $this->ChannelCollectionDao->get($id);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $update = $this->_filterUpdate($param);
        $update = array_merge($update, Arr::only($param, ['updateBy']));

        $oldList              = $this->ChannelCollectionConnDao->getWhereList(['collectionId' => $id]);
        $refreshChannelNoList = array_column($oldList, 'channelNo');

        Db::beginTransaction();

        try {

            $this->ChannelCollectionDao->update($id, $update);

            $param['payType'] = $info['payType']; // 从查询到的数据补充payType

            $this->_setConn($id, $param);

            // 通知风控模块刷新缓存
            $this->RiskSyncService->syncChannelCollection($refreshChannelNoList);

        } catch (\Throwable $e) {
            Db::rollBack();
            throw $e;
        }

        Db::commit();

        $data = ['id' => $id];
        return CustomUtils::buildSuccess($data);
    }

    /**
     * 删除
     *
     * @param $param
     *
     * @return array
     */
    public function del ($param) {

        $id = Arr::get($param, 'id');

        $result = $this->ChannelCollectionDao->get($param['id']);

        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $oldList              = $this->ChannelCollectionConnDao->getWhereList(['collectionId' => $id]);
        $refreshChannelNoList = array_column($oldList, 'channelNo');

        Db::beginTransaction();

        try {

            $this->ChannelCollectionDao->del($param['id'], false);

            $this->RiskSyncService->syncChannelCollection($refreshChannelNoList);

        } catch (\Throwable $e) {
            Db::rollBack();
            throw $e;
        }

        Db::commit();


        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE, XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), CustomUtils::xzxEmptyObject());
    }

    /**
     * 设置关联数据
     *
     * @param string $id
     * @param        $param
     */
    protected function _setConn (string $id, $param) {

        // 删除原来的
        $this->ChannelCollectionConnDao->delWhere(['collectionId' => $id]);

        $conn    = Arr::pull($param, 'conn', []);
        $payType = Arr::get($param, 'payType');

        $channelIdList = array_column($conn, 'channelId');


        // 筛选有效的,payType通道集合和通道的这个参数要一致
        $channelList = [];
        if (!empty($channelIdList)) {
            $channelList = $this->ChannelInfoDao->getWhereList(function (Builder $query) use ($channelIdList, $payType) {
                $query->whereIn('id', $channelIdList);
                $query->where('payType', $payType);
            });
        }

        if (empty($channelList)) {
            // 空集, 无需插入
            return;
        }

        $channelList = array_column($channelList, null, 'id');

        $prototype = [
            'createBy'     => $param['createBy'],
            'updateBy'     => $param['updateBy'],
            'collectionId' => $id,
        ];

        $insertList = [];

        foreach ($conn as $item) {

            if (isset($channelList[$item['channelId']])) {

                $channel = $channelList[$item['channelId']];

                array_push($insertList, array_merge($prototype, [
                    'sort'      => $item['sort'],
                    'channelNo' => $channel['channelNo'],
                    'id'        => StringUtils::uuidV4(),
                ]));
            }
        }

        // 批量插入
        $this->ChannelCollectionConnDao->add($insertList);
    }

    /**
     * 列表下拉框
     *
     * @param array $param
     *
     * @return array
     */
    public function options (array $param) {

        $list = $this->ChannelCollectionDao->getWhereList(function (Builder $query) use ($param) {
            !empty($param['search']) && $query->where('collectionName', 'like', "%{$param["search"]}%");
            !empty($param['payType']) && $query->where('payType', $param['payType']);
            // !empty($param['canPay']) && $query->where('canPay', $param['canPay']);
            // !empty($param['canRefund']) && $query->where('canRefund', $param['canRefund']);
            // !empty($param['canTransfer']) && $query->where('canTransfer', $param['canTransfer']);

            $query->where("status", 1);
        });

        $list = array_map(function ($item) {
            return [
                'value'   => $item['id'],
                'label'   => $item['collectionName'],
                'payType' => $item['payType'],
            ];
        }, $list);

        $data = $list;

        return CustomUtils::buildSuccess($data);
    }

    public function settleCurrencyList ($param) {
        $data = $this->ChannelCollectionDao->settleCurrencyList($param);
        return CustomUtils::buildSuccess($data);
    }

}
